/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.farmcode.base.dao;

import java.util.HashMap;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author oiprado
 */
public class BaseDAOImpl<T> implements BaseDAO<T> {

    @PersistenceContext
    protected EntityManager entityManager;
    protected HashMap<String, Object> parameters;
    protected String sqlQuery;
    private BaseFilter baseFilter;

    public BaseDAOImpl() {
        parameters = new HashMap<String, Object>();
    }

    @Override
    public void create(T entity) throws DAOException {
        try {
            entityManager.persist(entity);
        } catch (Exception e) {
            throw wrapDAOException(e);
        }
    }

    @Override
    public void store(T entity) throws DAOException {
        try {
            entityManager.merge(entity);
        } catch (Exception e) {
            throw wrapDAOException(e);
        }
    }

    @Override
    public void remove(T entity, Object primaryKey) throws DAOException {
        try {
            Object entityRemove = entityManager.find(entity.getClass(), primaryKey);
            if (entityRemove != null) {
                entityManager.remove(entityRemove);
            }
        } catch (Exception e) {
            throw wrapDAOException(e);
        }
    }

    
    
    @Override
    public List<T> find(BaseFilter baseFilter) throws DAOException {
        try {
            setFilter(baseFilter);
            return find();
        } catch (Exception e) {
            throw wrapDAOException(e);
        } finally {
            parameters.clear();
        }
    }

    @Override
    public List<T> find() throws DAOException {
        try {

            StringBuilder querys = new StringBuilder();
            
            querys.append(sqlQuery);
            
            final Query query = entityManager.createQuery(querys.toString());

            for (String key : parameters.keySet()) {
                query.setParameter(key, parameters.get(key));
            }
            return query.getResultList();
        } catch (Exception e) {
            throw wrapDAOException(e);
        } finally {
            parameters.clear();
        }
    }
    
    @Override
    public List<T> executeQuery(String sqlQuery) throws DAOException {
        try {
            final Query query = entityManager.createQuery(sqlQuery);

            for (String key : parameters.keySet()) {
                query.setParameter(key, parameters.get(key));
            }
            return query.getResultList();
        } catch (Exception e) {
            throw wrapDAOException(e);
        } finally {
            parameters.clear();
        }
       
    }

    protected String buildWhere() {
        StringBuilder where = new StringBuilder();
        if (baseFilter != null) {
            baseFilter.clear();
            baseFilter.fill();
            int size = baseFilter.getKeys().size();

            if (size > 0) {
                where.append(" where ");
                for (int index = 0; index < size; index++) {
                    String key = baseFilter.getKeys().get(index);

                    StringBuilder condition = new StringBuilder();

                    condition.append(baseFilter.getConditions().get(key));
                    condition.append(":");
                    condition.append(baseFilter.getKeys().get(index));

                    if (index < size - 1) {
                        condition.append(" and ");
                    }
                    where.append(condition);
                    parameters.put(key, baseFilter.getValues().get(key));
                }
            }

        }

        return where.toString();
    }

    private DAOException wrapDAOException(Exception ex) {
        return new DAOException(ex);
    }

    @Override
    public void setFilter(BaseFilter baseFilter) {
        this.baseFilter = baseFilter;
    }

    @Override
    public boolean isAttached(Object entity) {
        return entityManager.contains(entity);
    }
}
